﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Security.Authentication.Web;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;
using Windows.Web.Http;
using Windows.Web.Http.Headers;

namespace F2S.OAuth
{
    public class OAuthBase
    {
        public enum SignatureTypes
        {
            HMACSHA1,
            PLAINTEXT,
            RSASHA1
        }

        protected const string _oAuthVersion = "1.0";
        protected const string _oAuthParameterPrefix = "oauth_";

        protected const string _oAuthConsumerKeyKey = "oauth_consumer_key";
        protected const string _oAuthCallbackKey = "oauth_callback";
        protected const string _oAuthVersionKey = "oauth_version";
        protected const string _oAuthSignatureMethodKey = "oauth_signature_method";
        protected const string _oAuthSignatureKey = "oauth_signature";
        protected const string _oAuthTimestampKey = "oauth_timestamp";
        protected const string _oAuthNonceKey = "oauth_nonce";
        protected const string _oAuthTokenKey = "oauth_token";
        protected const string _oAauthVerifier = "oauth_verifier";
        protected const string _oAuthTokenSecretKey = "oauth_token_secret";

        protected const string _HMACSHA1SignatureType = "HMAC-SHA1";
        protected const string _PlainTextSignatureType = "PLAINTEXT";
        protected const string _RSASHA1SignatureType = "RSA-SHA1";

        protected static Random _random = new Random();

        private string _oauth_verifier;
        public string Verifier { get { return _oauth_verifier; } set { _oauth_verifier = value; } }

        protected string _unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";


        public static string generateSignature(string sigBaseString, string consumerSecretKey, string k2)
        {
            var KeyMaterial = CryptographicBuffer.ConvertStringToBinary(consumerSecretKey + "&" + k2, BinaryStringEncoding.Utf8);
            var HmacSha1Provider = MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA1");
            var MacKey = HmacSha1Provider.CreateKey(KeyMaterial);
            var DataToBeSigned = CryptographicBuffer.ConvertStringToBinary(sigBaseString, BinaryStringEncoding.Utf8);
            var SignatureBuffer = CryptographicEngine.Sign(MacKey, DataToBeSigned);
            var signature = CryptographicBuffer.EncodeToBase64String(SignatureBuffer);

            return signature;
        }

        public static string generateSignature(string sigBaseString, string consumerSecretKey)
        {
            var KeyMaterial = CryptographicBuffer.ConvertStringToBinary(consumerSecretKey + "&", BinaryStringEncoding.Utf8);
            var HmacSha1Provider = MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA1");
            var MacKey = HmacSha1Provider.CreateKey(KeyMaterial);
            var DataToBeSigned = CryptographicBuffer.ConvertStringToBinary(sigBaseString, BinaryStringEncoding.Utf8);
            var SignatureBuffer = CryptographicEngine.Sign(MacKey, DataToBeSigned);
            var Signature = CryptographicBuffer.EncodeToBase64String(SignatureBuffer);

            return Signature;
        }

        public static string generateTimeStamp()
        {
            // Default implementation of UNIX time of the current UTC time
            var ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        public static string generateNonce()
        {
            // Just a simple implementation of a random number between 123400 and 9999999
            return _random.Next(123400, 9999999).ToString();
        }

        private string _requestToken;
        private string _userSecret;
        private string _apiKey;
        private string _apiSecret;

        private string _nonce;
        private string _timestamp;

        public OAuthBase()
        {
            
        }

        public OAuthBase(string apiKey, string apiSecret)
        {
            _apiKey = apiKey;
            _apiSecret = apiSecret;
        }
        public OAuthBase(string requestToken, string userSecret, string apiKey, string apiSecret, string nonce = null, string timestamp = null)
        {
            _requestToken = requestToken;
            _userSecret = userSecret;
            _apiKey = apiKey;
            _apiSecret = apiSecret;
            _nonce = nonce;
            _timestamp = timestamp;
        }

        async public Task<System.Net.Http.HttpResponseMessage> execute(string requestUrl, string method)
        {
            var timeStamp = _timestamp ?? generateTimeStamp();
            var nonce = _nonce ?? generateNonce();

            var parms = "oauth_consumer_key=" + _apiKey;
            parms += "&" + "oauth_nonce=" + nonce;
            parms += "&" + "oauth_signature_method=HMAC-SHA1";
            parms += "&" + "oauth_timestamp=" + timeStamp;
            parms += "&" + "oauth_token=" + _requestToken;
            parms += "&" + "oauth_version=1.0";
            var sigBaseString = method + "&";
            sigBaseString += Uri.EscapeDataString(requestUrl) + "&" + Uri.EscapeDataString(parms);

            var signature = generateSignature(sigBaseString, _apiSecret, _userSecret);
            //"S6ijg523yu4SaWq9",
            //"9affca5d-b6fa-457a-be63-adfd47d4669b"
            //);

            var httpContent = new HttpStringContent(sigBaseString);// "oauth_verifier=" + oauth_verifier, Windows.Storage.Streams.UnicodeEncoding.Utf8);
            httpContent.Headers.ContentType = HttpMediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
            /*
            var authorizationHeaderParams =
                "oauth_consumer_key=\"" + _apiKey + "\", oauth_nonce=\"" + nonce + "\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"" + Uri.EscapeDataString(signature) +
                "\", oauth_timestamp=\"" + timeStamp + "\", oauth_token=\"" + Uri.EscapeDataString(_requestToken) + "\", oauth_version=\"1.0\"";
            */

            parms =
                "oauth_consumer_key=" + _apiKey + "&" +
                "oauth_nonce=" + nonce + "&" +
                "oauth_signature=" + Uri.EscapeDataString(signature) + "&" +
                "oauth_signature_method=HMAC-SHA1&" +
                "oauth_timestamp=" + timeStamp + "&" +
                "oauth_token=" + Uri.EscapeDataString(_requestToken) + "&" +
                "oauth_version=1.0";

            var httpClient = new System.Net.Http.HttpClient();

            try
            {
                var httpResponseMessage = await httpClient.GetAsync(requestUrl + "?");
                return httpResponseMessage;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        async public Task<string> getOAuthTokens(string requestTokenUrl)
        {
            var nonce = generateNonce();
            var timestamp = generateTimeStamp();

            var parms = "oauth_callback=" + Uri.EscapeDataString("http://getglue.42spikes.com");
            parms += "&" + "oauth_consumer_key=" + _apiKey;
            parms += "&" + "oauth_nonce=" + nonce;
            parms += "&" + "oauth_signature_method=HMAC-SHA1";
            parms += "&" + "oauth_timestamp=" + timestamp;
            parms += "&" + "oauth_version=1.0";
            var sigbase = "GET" + "&";
            sigbase += Uri.EscapeDataString(requestTokenUrl) + "&" + Uri.EscapeDataString(parms);
            var signature = generateSignature(sigbase, _apiSecret);

            var url = requestTokenUrl + "?" + parms + "&oauth_signature=" + Uri.EscapeDataString(signature);
            var client = new HttpClient();
            var response = await client.GetStringAsync(new Uri(url));

            var keyValPairs = response.Split('&');

            foreach (var t in keyValPairs)
            {
                var splits = t.Split('=');
                switch (splits[0])
                {
                    case "oauth_token":
                        _requestToken = splits[1];
                        break;
                    case "oauth_token_secret":
                        _userSecret = splits[1];
                        break;
                }
            }

            return _requestToken;
        }

        async public Task authorize(string authorizeUrlBase, string requestToken)
        {
            var requestUrl = authorizeUrlBase + "?oauth_token=" + requestToken;
            var war = await WebAuthenticationBroker.AuthenticateAsync(
                WebAuthenticationOptions.None,
                new Uri(requestUrl),
                new Uri("http://getglue.42spikes.com"));
        }
    }
}
